ansible 命令使用手册
什么是命令通道?
有时候一些简单任务,没必要写复杂的playbook,所以大多时候我们可以通过ansible命令行来批量操控目标机器
当我们需要批量操作、查看一组机器,或者在这些机器上批量执行某个命令、修改某个文件,都可以通过命令通道在一台机器上批量并发完成对所有机器的操作
命令通道只是一个帮你将命令发送到多个目标机器,并将执行结果返回来给你的一个执行通道
使用场景
- 执行一行命令就能看到几十台机器的负载情况
- 批量执行远程服务器上已经写好的Shell脚本
- 查看所有Web服务器最近10000行Log中有没有ERROR
- 查看所有DB服务器的内存使用情况
- 批量将所有Diamond服务器的某个端口从7000改成9000
开始准备
如果不想每次输入ssh密码的话请提前将本地公钥(~/.ssh/id_rsa.pub 没有的话 ssh-keygen生成一对)复制到目标机器的 ~/.ssh/authorized_keys 里面,否则每次执行命令都要输入密码
编写一个 hosts.ini 配置文件,内容如下:
1 | [server] |
server/worker/target表示将7台机器分成了三组,可以到所有7台机器执行同一个命令,也可以只在server/worker/target中的一组机器上执行某个命令.all代表所有7台机器
运行命令行
查看 hosts.ini 里面所有服务器的 uptime
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
$ ansible -i hosts.ini all -m raw -a " uptime " -u admin
/usr/bin/ansible -i hosts.ini all -m raw -a uptime -u admin
success => 10.125.12.174 => rc=0 =>
11:10:50 up 27 days, 15:40, 1 user, load average: 0.05, 0.03, 0.05
success => 120.26.116.193 => rc=0 =>
11:10:50 up 13 days, 21:07, 1 user, load average: 0.00, 0.00, 0.00
命令参数说明
> __all:__ 表示对hosts.ini里面的所有服务器执行后面的命令
> __-i:__ 指定hosts.ini文件所在的位置
> __-m raw -a:__ 指定需要执行的命令
> __" uptime "__ 双引号里面写上需要执行的命令
> __-u admin__ 表示通过用户名admin 去执行命令【如果没有做好免密码,请加上 -k 参数,会出来提示输入SSH密码】
### 查看 hosts.ini 里面 server 组服务器的 home目录下的文件结构
$ ansible -i hosts.ini server -m raw -a " ls -lh ~/ " -u admin
/usr/bin/ansible -i hosts.ini server -m raw -a ls -lh ~/ -u admin
success => 10.125.0.169 => rc=0 =>
total 12K
drwxr-xr-x 2 root root 4.0K Nov 13 12:34 files
drwxr-xr-x 11 admin admin 4.0K Oct 20 10:49 tomcat
drwxr-xr-x 3 test games 4.0K Nov 18 15:40 ansible-engine
success => 10.125.3.33 => rc=0 =>
total 20K
-rw------- 1 admin admin 1.4K Nov 12 13:39 authorized_keys
drwxr-xr-x 2 root root 4.0K Nov 12 16:24 engine
drwxr-xr-x 2 root root 4.0K Nov 13 12:22 files
drwxr-xr-x 11 admin admin 4.0K Nov 18 15:43 tomcat
drwxr-xr-x 3 test games 4.0K Nov 18 15:40 ansible-engine
### 查看部分机器 hostname
ansible -i ccb_test.ini 192.168.2.10* -m shell -a ‘hostname ‘
[WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see details
192.168.2.100 | CHANGED | rc=0 >>
az2-drds-100
192.168.2.106 | CHANGED | rc=0 >>
az2-manager-106
192.168.2.101 | CHANGED | rc=0 >>
az2-alisql-101
192.168.2.102 | CHANGED | rc=0 >>
az2-alisql-102
192.168.2.105 | CHANGED | rc=0 >>
az2-alisql-105
192.168.2.104 | CHANGED | rc=0 >>
az2-alisql-104
192.168.2.103 | CHANGED | rc=0 >>
az2-alisql-103
192.168.2.107 | CHANGED | rc=0 >>
az2-manager-107
1 |
|
#config /etc/hosts
ansible -i $1 all -m shell -a “ sed -i ‘/registry/d’ /etc/hosts “
ansible -i $1 all -m shell -a “ echo ‘ registry’ >/etc/hosts “
ansible -i $1 all -m shell -a “ echo ‘ hostname
‘ >>/etc/hosts “
ansible -i $1 diamond -m shell -a “ echo ‘ jmenv.tbsite.net’ >> /etc/hosts “ -u root
//修改机器hostname
ansible -i $1 all -m shell -a “ hostnamectl set-hostname=’drds-‘ “ -u root
//修改机器hostname -i
ansible -i $1 all -m shell -a “ echo ‘ drds-‘ >> /etc/hosts “ -u root
//hostname 修改机器名
ansible -i ccb_test.ini 192.168.2.101 -m hostname -a “ name=az2-alisql-101 “
[WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see details
192.168.2.101 | CHANGED => {
“ansible_facts”: {
“ansible_domain”: “”,
“ansible_fqdn”: “iZ2ze9aj0re2ggbqa4dgxkZ”,
“ansible_hostname”: “az2-alisql-101”,
“ansible_nodename”: “az2-alisql-101”,
“discovered_interpreter_python”: “/usr/bin/python”
},
“changed”: true,
“name”: “az2-alisql-101”
}
1 |
|
ansible -i ccb_test.ini 192.168.2.101 -m service -a “ name=docker enabled=yes state=restarted “
[WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see details
192.168.2.101 | CHANGED => {
“ansible_facts”: {
“discovered_interpreter_python”: “/usr/bin/python”
},
“changed”: true,
“enabled”: true,
“name”: “docker”,
“state”: “started”,
“status”: {
“ActiveEnterTimestamp”: “二 2020-05-12 19:03:57 CST”,
“ActiveEnterTimestampMonotonic”: “1553024093129”,
“ActiveExitTimestamp”: “二 2020-05-12 19:01:24 CST”,
“ActiveExitTimestampMonotonic”: “1552870910912”,
“ActiveState”: “active”,
“After”: “systemd-journald.socket system.slice docker.socket firewalld.service containerd.service network-online.target basic.target”,
“AllowIsolate”: “no”,
“AmbientCapabilities”: “0”,
“AssertResult”: “yes”,
“AssertTimestamp”: “二 2020-05-12 19:03:57 CST”,
“AssertTimestampMonotonic”: “1553023902297”,
“Before”: “multi-user.target shutdown.target”,
“BindsTo”: “containerd.service”,
“BlockIOAccounting”: “no”,
“BlockIOWeight”: “18446744073709551615”,
“CPUAccounting”: “no”,
“CPUQuotaPerSecUSec”: “infinity”,
“CPUSchedulingPolicy”: “0”,
“CPUSchedulingPriority”: “0”,
“CPUSchedulingResetOnFork”: “no”,
“CPUShares”: “18446744073709551615”,
“CanIsolate”: “no”,
“CanReload”: “yes”,
“CanStart”: “yes”,
“CanStop”: “yes”,
“CapabilityBoundingSet”: “18446744073709551615”,
“ConditionResult”: “yes”,
“ConditionTimestamp”: “二 2020-05-12 19:03:57 CST”,
“ConditionTimestampMonotonic”: “1553023902297”,
“Conflicts”: “shutdown.target”,
“ConsistsOf”: “docker.socket”,
“ControlGroup”: “/system.slice/docker.service”,
“ControlPID”: “0”,
“DefaultDependencies”: “yes”,
“Delegate”: “yes”,
“Description”: “Docker Application Container Engine”,
“DevicePolicy”: “auto”,
“Documentation”: “https://docs.docker.com“,
“ExecMainCode”: “0”,
“ExecMainExitTimestampMonotonic”: “0”,
“ExecMainPID”: “16213”,
“ExecMainStartTimestamp”: “二 2020-05-12 19:03:57 CST”,
“ExecMainStartTimestampMonotonic”: “1553023907468”,
“ExecMainStatus”: “0”,
“ExecReload”: “{ path=/bin/kill ; argv[]=/bin/kill -s HUP $MAINPID ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }”,
“ExecStart”: “{ path=/usr/bin/dockerd ; argv[]=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2376 –data-root=/var/lib/docker –log-opt max-size=50m –log-opt max-file=3 –registry-mirror=https://oqpc6eum.mirror.aliyuncs.com –containerd=/run/containerd/containerd.sock ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }”,
“FailureAction”: “none”,
“FileDescriptorStoreMax”: “0”,
“FragmentPath”: “/usr/lib/systemd/system/docker.service”,
“GuessMainPID”: “yes”,
“IOScheduling”: “0”,
“Id”: “docker.service”,
“IgnoreOnIsolate”: “no”,
“IgnoreOnSnapshot”: “no”,
“IgnoreSIGPIPE”: “yes”,
“InactiveEnterTimestamp”: “二 2020-05-12 19:03:43 CST”,
“InactiveEnterTimestampMonotonic”: “1553009791884”,
“InactiveExitTimestamp”: “二 2020-05-12 19:03:57 CST”,
“InactiveExitTimestampMonotonic”: “1553023907496”,
“JobTimeoutAction”: “none”,
“JobTimeoutUSec”: “0”,
“KillMode”: “process”,
“KillSignal”: “15”,
“LimitAS”: “18446744073709551615”,
“LimitCORE”: “18446744073709551615”,
“LimitCPU”: “18446744073709551615”,
“LimitDATA”: “18446744073709551615”,
“LimitFSIZE”: “18446744073709551615”,
“LimitLOCKS”: “18446744073709551615”,
“LimitMEMLOCK”: “65536”,
“LimitMSGQUEUE”: “819200”,
“LimitNICE”: “0”,
“LimitNOFILE”: “18446744073709551615”,
“LimitNPROC”: “18446744073709551615”,
“LimitRSS”: “18446744073709551615”,
“LimitRTPRIO”: “0”,
“LimitRTTIME”: “18446744073709551615”,
“LimitSIGPENDING”: “379870”,
“LimitSTACK”: “18446744073709551615”,
“LoadState”: “loaded”,
“MainPID”: “16213”,
“MemoryAccounting”: “no”,
“MemoryCurrent”: “58327040”,
“MemoryLimit”: “18446744073709551615”,
“MountFlags”: “0”,
“Names”: “docker.service”,
“NeedDaemonReload”: “no”,
“Nice”: “0”,
“NoNewPrivileges”: “no”,
“NonBlocking”: “no”,
“NotifyAccess”: “main”,
“OOMScoreAdjust”: “0”,
“OnFailureJobMode”: “replace”,
“PermissionsStartOnly”: “no”,
“PrivateDevices”: “no”,
“PrivateNetwork”: “no”,
“PrivateTmp”: “no”,
“ProtectHome”: “no”,
“ProtectSystem”: “no”,
“RefuseManualStart”: “no”,
“RefuseManualStop”: “no”,
“RemainAfterExit”: “no”,
“Requires”: “docker.socket basic.target”,
“Restart”: “always”,
“RestartUSec”: “2s”,
“Result”: “success”,
“RootDirectoryStartOnly”: “no”,
“RuntimeDirectoryMode”: “0755”,
“SameProcessGroup”: “no”,
“SecureBits”: “0”,
“SendSIGHUP”: “no”,
“SendSIGKILL”: “yes”,
“Slice”: “system.slice”,
“StandardError”: “inherit”,
“StandardInput”: “null”,
“StandardOutput”: “journal”,
“StartLimitAction”: “none”,
“StartLimitBurst”: “3”,
“StartLimitInterval”: “60000000”,
“StartupBlockIOWeight”: “18446744073709551615”,
“StartupCPUShares”: “18446744073709551615”,
“StatusErrno”: “0”,
“StopWhenUnneeded”: “no”,
“SubState”: “running”,
“SyslogLevelPrefix”: “yes”,
“SyslogPriority”: “30”,
“SystemCallErrorNumber”: “0”,
“TTYReset”: “no”,
“TTYVHangup”: “no”,
“TTYVTDisallocate”: “no”,
“TasksAccounting”: “no”,
“TasksCurrent”: “58”,
“TasksMax”: “18446744073709551615”,
“TimeoutStartUSec”: “0”,
“TimeoutStopUSec”: “0”,
“TimerSlackNSec”: “50000”,
“Transient”: “no”,
“TriggeredBy”: “docker.socket”,
“Type”: “notify”,
“UMask”: “0022”,
“UnitFilePreset”: “disabled”,
“UnitFileState”: “enabled”,
“WantedBy”: “multi-user.target”,
“Wants”: “network-online.target system.slice”,
“WatchdogTimestamp”: “二 2020-05-12 19:03:57 CST”,
“WatchdogTimestampMonotonic”: “1553024093096”,
“WatchdogUSec”: “0”
}
}
1 |
|
$ ansible -i hosts.ini server -m raw -a “ which nc ; find /opt/aliUDP/logs/ “ -u admin
/usr/bin/ansible -i hosts.ini server -m raw -a which nc ; find /opt/aliUDP/logs/ -u admin
FAILED => 120.26.116.193 => rc=1 =>
which: no nc in (/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin)
find: /opt/aliUDP: No such file or directory
success => 10.125.3.33 => rc=0 =>
/usr/bin/nc
/opt/aliUDP/logs/
/opt/aliUDP/logs/ansible.log.bak
/opt/aliUDP/logs/ansible.log
success => 10.125.0.169 => rc=0 =>
/usr/bin/nc
/opt/aliUDP/logs/
/opt/aliUDP/logs/ansible.log.bak
/opt/aliUDP/logs/ansible.log
1 |
|
$ ansible -i hosts.ini server -m copy -a “ src=’~/.ssh/id_rsa.pub’ dest=’/tmp/‘ owner=admin “ -u admin
SUCCESS => 120.26.116.193 => {
“changed”: true,
“checksum”: “b12ccf236ab788bbaebd7159c563e97411389c9e”,
“dest”: “/tmp/id_rsa.pub”,
“gid”: 0,
“group”: “root”,
“md5sum”: “b6ba28284ab95aaa0f47602bdab49f46”,
“mode”: “0644”,
“owner”: “root”,
“size”: 392,
“src”: “/root/.ansible/ansible-tmp-1449109886.94-70134064194486/source”,
“state”: “file”,
“uid”: 0
}
SUCCESS => 10.125.0.169 => {
“changed”: true,
“checksum”: “b12ccf236ab788bbaebd7159c563e97411389c9e”,
“dest”: “/tmp/id_rsa.pub”,
“gid”: 500,
“group”: “admin”,
“md5sum”: “b6ba28284ab95aaa0f47602bdab49f46”,
“mode”: “0664”,
“owner”: “admin”,
“size”: 392,
“src”: “/home/admin/.ansible/ansible-tmp-1449109886.78-98797505042348/source”,
“state”: “file”,
“uid”: 500
}
SUCCESS => 10.125.3.33 => {
“changed”: true,
“checksum”: “b12ccf236ab788bbaebd7159c563e97411389c9e”,
“dest”: “/tmp/id_rsa.pub”,
“gid”: 500,
“group”: “admin”,
“md5sum”: “b6ba28284ab95aaa0f47602bdab49f46”,
“mode”: “0664”,
“owner”: “admin”,
“size”: 392,
“src”: “/home/admin/.ansible/ansible-tmp-1449109886.81-269249309502640/source”,
“state”: “file”,
“uid”: 500
}
1 | 参数说明 |
$ ansible -i hosts.ini server -m command -a “ md5sum /tmp/id_rsa.pub “ -u admin
success => 10.125.0.169 => rc=0 =>
b6ba28284ab95aaa0f47602bdab49f46 /tmp/id_rsa.pub
success => 10.125.3.33 => rc=0 =>
b6ba28284ab95aaa0f47602bdab49f46 /tmp/id_rsa.pub
success => 120.26.116.193 => rc=0 =>
b6ba28284ab95aaa0f47602bdab49f46 /tmp/id_rsa.pub
1 | 结果说明 |
$ cat test.sh
#/bin/sh
ifconfig | grep ‘inet addr’
echo “————-“
uptime
echo “————-“
date
df -lh
1 | 执行结果 |
copy个人笔记本的公钥到服务器上,以后从笔记本登录服务器不再需要输入密码
1 | $ ansible -i ansible-hosts.ini all -m authorized_key -a " user=admin key=\"{{ lookup('file', '/tmp/id_rsa.pub') }} \" " -u admin -k |
Copying files between different folders on the same remote machine
You can also copy files between the various locations on the remote servers. You have to set the remote_src parameter to yes.
The following example copies the hello6 file in the /tmp directory of the remote server and pastes it in the /etc/ directory.
1 | - hosts: blocks |
or:
1 | ansible blocks -m copy -a "src=/tmp/hello6 dest=/tmp/hello7etc remote_src=yes" -s -i inventory.ini |
效率更高的 copy:synchronize
1 | ansible -i xty_172.ini all -m synchronize -a " src=/home/ren/docker.service dest=/usr/lib/systemd/system/docker.socket " -u root |
find_file
1 | - hosts: all |
test
1 | ansible-playbook -i 127.0.0.1, ./find_file.yaml |
不使用 hosts.ini文件,从命令行中传入目标机的 ip 列表
1 | $ ansible -i 10.125.0.169,10.125.192.40 all -e "ansible_ssh_port=22" -a "uptime" -u admin |
执行说明
-i 后面带入ip列表,注意每个IP后面一定要有 “,” 分割开来,all 关键字也是必须的
-e 中ansible_ssh_port=22表示ssh使用22端口(默认),如果ssh使用9999端口在这里将22改成9999即可
使用root sudo权限来执行命令
1 | ansible -i 10.125.6.93, all -m shell -a " ls -lh /home/admin/" -u admin --become-user=root --ask-become-pass --become-method=sudo --become -k |
给admin授权登录server不需要输入密码(也不知道admin的密码)
1 | 通过 admin(已知密码) 以root 权限将本机pub key复制到server上的 /home/admin, 再通过admin账号登录server就不需要密码了: |
fetch:将远程服务器上的public key 读取到本地
1 | ansible -i kfc.ini hadoop -m fetch -a " src=/home/admin/.ssh/id_rsa.pub dest=./test/ " -u admin |
或者循环fetch:
1 | $cat fetch.yaml |
执行结果:
1 | $ansible-playbook -i /home/aliyun/all.ini fetch.yaml -u admin |
setup:获取机器配置、参数信息
1 | # ansible -i 192.168.1.91, all -m setup -u admin |
ansible + xargs 占位符
1 | //批量执行docker exec |
指定ip执行playbook
ansible-playbook -i “10.168.101.179,” all test.yml
或者:
ansible -i phy.ini 11.167.60.150 -m shell -a ‘docker run -it -d –net=host -e diamond_server_list=”“ -e diamond_db0=”“ -e diamond_db1=”“ -e diamond_db2=”“ -e HOST_IP=”“ -p 8080:8080 -p 9090:9090 –name diamond ‘ -vvv
上面这种还能重用phy.ini中所有的变量配置
创建用户并打通账号
1 | $cat create_user.yml |
然后执行: ansible-playbook -i all.ini create_user.yml -e “user=admin” 。
或者:
1 | ansible -i 192.168.2.101, all -m user -a "name=user02 system=yes uid=503 group=root groups=root shell=/etc/nologin home=/home/user02 password=pwd@123" |
playbook task规范:
对齐的时候不能用tab和空格混合
修改密码
创建如下yaml脚本 changepw.yml:
1 | - name: user module demo |
使用方法:
1 | ansible-playbook -i 1.2.3.4, changepw.yml -e "user=root" -e "mypassword=123" |
将 root 账号的密码改成123
或者:
1 | ansible -i 1.2.3.4, all -e "newpassword=1234" -m user -a "name=admin update_password=always password={{ newpassword|password_hash('sha512') }}" |
创建用户以及密码
1 | ansible -i 1.2.3.4, all -e "newpassword=1234" -m user -a "name=ren state=present shell=/bin/sh update_password=always password={{ newpassword|password_hash('sha512') }}" |
部署docker daemon的playbook
执行 ansible-playbook site.yml -v -i test.ini -u admin -e “project=docker” -p
1 | $cat roles/docker/tasks/main.yml |
部署zk
1 | $cat roles/zookeeper/tasks/main.yml |
参考资料
How to Copy Files and Directories in Ansible Using Copy and Fetch Modules